package cn.com.ry.framework.linklog.gateway.common;

import cn.com.ry.framework.linklog.constant.LinkLogConstants;
import cn.com.ry.framework.linklog.context.SpanIdGenerator;
import cn.com.ry.framework.linklog.core.LinkLogLabel;
import cn.com.ry.framework.linklog.core.LinkLogHandler;
import cn.com.ry.framework.linklog.util.HostInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;

import java.util.List;
import java.util.function.Consumer;

public class LinkLogGatewayCommon extends LinkLogHandler {

    private final static Logger log = LoggerFactory.getLogger(LinkLogGatewayCommon.class);

    private static volatile LinkLogGatewayCommon linkLogGatewayCommon;

    private static final Integer FIRST = 0;

    public static LinkLogGatewayCommon loadInstance() {
        if (linkLogGatewayCommon == null) {
            synchronized (LinkLogGatewayCommon.class) {
                if (linkLogGatewayCommon == null) {
                    linkLogGatewayCommon = new LinkLogGatewayCommon();
                }
            }
        }
        return linkLogGatewayCommon;
    }

    public ServerWebExchange preHandle(ServerWebExchange exchange) {
        String traceId = null;
        String spanId = null;
        String preApp = null;
        String preHost = null;
        String preIp = null;
        HttpHeaders headers = exchange.getRequest().getHeaders();
        List<String> traceIds = headers.get(LinkLogConstants.LINKLOG_TRACE_KEY);
        if (traceIds != null && traceIds.size() > 0) {
            traceId = traceIds.get(FIRST);
        }
        List<String> spanIds = headers.get(LinkLogConstants.LINKLOG_SPANID_KEY);
        if (spanIds != null && spanIds.size() > 0) {
            spanId = spanIds.get(FIRST);
        }
        List<String> preApps = headers.get(LinkLogConstants.LINKLOG_PRE_APP_KEY);
        if (preApps != null && preApps.size() > 0) {
            preApp = preApps.get(FIRST);
        }
        List<String> preHosts = headers.get(LinkLogConstants.LINKLOG_PRE_HOST_KEY);
        if (preHosts != null && preHosts.size() > 0) {
            preHost = preHosts.get(FIRST);
        }
        List<String> preIps = headers.get(LinkLogConstants.LINKLOG_PRE_IP_KEY);
        if (preIps != null && preIps.size() > 0) {
            preIp = preIps.get(FIRST);
        }

        LinkLogLabel labelBean = new LinkLogLabel(preApp, preHost, preIp, traceId, spanId);

        processProviderSide(labelBean);

        String tmp_traceId = labelBean.getTraceId();
        if (tmp_traceId != null && !tmp_traceId.equals("")) {

            Consumer<HttpHeaders> httpHeaders = httpHeader -> {
                httpHeader.set(LinkLogConstants.LINKLOG_TRACE_KEY, tmp_traceId);
                httpHeader.set(LinkLogConstants.LINKLOG_SPANID_KEY, SpanIdGenerator.generateNextSpanId());
                httpHeader.set(LinkLogConstants.LINKLOG_PRE_APP_KEY, HostInfo.getAppName());
                httpHeader.set(LinkLogConstants.LINKLOG_PRE_HOST_KEY, HostInfo.getHostName());
                httpHeader.set(LinkLogConstants.LINKLOG_PRE_IP_KEY, HostInfo.getIp());
            };
            ServerHttpRequest serverHttpRequest = exchange.getRequest().mutate().headers(httpHeaders).build();
            return exchange.mutate().request(serverHttpRequest).build();
        } else {
            log.debug("[LinkLog]本地threadLocal变量没有正确传递traceId,本次调用不传递traceId");
            return exchange;
        }
    }

}
